﻿using System;
using System.Reflection;
using IInject.Internal;

namespace IInject.Resolution
{
	public class DefaultConstructorSelector : ContainerMember, IConstructorSelector
	{
		#region Constructors

		public DefaultConstructorSelector(IContainer container) : base(container)
		{
			DependencyResolver = container.Resolver;
		}

		#endregion

		#region Properties

		protected IDependencyResolver DependencyResolver { get; private set; }

		#endregion

		#region Methods

		public virtual ConstructorDependency Select(TypeDependency type)
		{
			var ctors = GetConstructors(type.Dependent);

			if (ctors.Length == 1 && ctors[0].GetParameters().Length == 0)
			{
				return new ConstructorDependency(ctors[0]);
			}

			return null;
		}

		protected virtual ConstructorInfo[] GetConstructors(Type type)
		{
			return new[] { type.GetConstructor(Type.EmptyTypes) };
		}

		protected virtual ConstructorDependency Select(ConstructorInfo[] ctors)
		{
			for (int i = 0; i < ctors.Length; i++)
			{
				var parameters = ctors[i].GetParameters();

				if (CanResolveParameters(parameters))
				{
					return new ConstructorDependency(ctors[i]);
				}
			}

			return null;
		}

		protected virtual bool CanResolveParameters(ParameterInfo[] parameters)
		{
			for (int i = 0; i < parameters.Length; i++)
			{
				if (!DependencyResolver.CanResolve(parameters[i].ParameterType))
				{
					return false;
				}
			}

			return true;
		}

		#endregion
	}
}
